/****************************************************************************
 *  Sample client program to test the following XP functions:
 *     XPrsa()
 *     XPeq()
 *     XPsub()
 *     XPrand()
 *
 *  Compilation:  gcc126 testrsa.c xp.c
 *  Execution:    a.out
 *
 *  If anything is printed, you probably have a bug.
 *
 ****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "XP.h"
#define TRIALS 50


/**************************************************
 *  check that a ^ b mod n = c
 **************************************************/
int test_rsa(XP a, XP b, XP n, XP c) {
  if(!XPeq(XPrsa(a, b, n), c)) {
       printf("Error detected while running testrsa.c\n");
      printf("a              = "); XPshowDecimal(a); printf("\n");
      printf("b              = "); XPshowDecimal(b); printf("\n");
      printf("n              = "); XPshowDecimal(n); printf("\n");
      printf("a^b mod n      = "); XPshowDecimal(c); printf("\n");
      printf("XPrsa(a, b, n) = "); XPshowDecimal(XPrsa(a, b, n)); printf("\n");
      printf("\n");

      return 1;
   }

   return 0;
}


/************************************************************
 *  Sample client to help test modular exponentiation
 *  Assumes XPeq(), XPsub(), XPmod() works correctly.
 ************************************************************/
bool test_rsa(void) {
        bool result = true;
   int i;
   XP a, p;
   XP ZERO = XPinitDecimal("0");
   XP ONE = XPinitDecimal("1");

   srand((unsigned int) time(NULL));

   // check modular exponentation for internal consistency
   // if a is not a multiple of a prime p, then Fermat's little theorem
   // asserts a ^ (p-1) mod p = 1
   p = XPinitDecimal("197");
   for (i = 0; i < TRIALS; i++) {
      a = XPrand(N);
      if (!XPeq(XPmod(a, p), ZERO))
              if (test_rsa(a, XPsub(p, ONE), p, ONE)) { result = false; break; }
   }

   p = XPinitDecimal("55103");
   for (i = 0; i < TRIALS; i++) {
      a = XPrand(N);
      if (!XPeq(XPmod(a, p), ZERO))
              if (test_rsa(a, XPsub(p, ONE), p, ONE)) { result = false; break; }
   }

   p = XPinitDecimal("67865665656555656597");
   for (i = 0; i < TRIALS; i++) {
      a = XPrand(N);
      if (!XPeq(XPmod(a, p), ZERO))
              if (test_rsa(a, XPsub(p, ONE), p, ONE)) { result = false; break; }
   }

   return result;
}

